//
//  ViewController.m
//  iOS_Multithread
//
//  Created by Scott on 16/2/24.
//  Copyright © 2016年 Scott. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

@property (retain, nonatomic) IBOutlet UIImageView *imageView;

@end

@implementation ViewController

/** 执行一段代码. 目的, 让CPU运行一段时间 */
- (void)snippet {
    
    /** 查看此段代码在哪个线程中执行 */
    NSLog(@"snippet thread:%@", [NSThread currentThread]);
    NSLog(@"snippet isMainThread?:%d", [NSThread isMainThread]);
    
    
    NSInteger sum = 0;
    for (long int i = 0; i < 1000000000; i++) {
        sum = sum + i;
    }
    
    NSLog(@"%ld", sum);
    
}

- (IBAction)handleTest:(id)sender {
    
    [self snippet];
    
}


#pragma mark - 知识点1 线程管理(NSObject方法)
- (IBAction)handleNSObject:(id)sender {
    
    NSLog(@"%s thread:%@", __func__, [NSThread currentThread]);
    
    
    [self performSelectorInBackground:@selector(snippet) withObject:nil];
    
}


#pragma mark - 知识点2 线程管理(NSThread)
- (IBAction)handleThread:(id)sender {
    
    /* NSThread类, 线程类, 一个线程对象就是一个线程 */
    
#if 0 /* 方法1: */
    /* 创建一个线程对象 */
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(snippet) object:nil];
    
    /* name */
    thread.name = @"sum";
    
    /* 开始线程 */
    [thread start];
    
    
    [thread release];
    
#endif
    
    
#if 1 /* 方法2: */
    
    [NSThread detachNewThreadSelector:@selector(snippet) toTarget:self withObject:nil];
    
    
#endif
    
}


#pragma mark - 知识点3 线程管理(NSOperationQueue)
- (IBAction)handleOperatoinQueue:(id)sender {
    
    /**
     * 涉及到两个类: NSOperation, NSOperationQueue
     *
     * 一个NSOperationQueue是一个线程
     *
     * 要实现多线程, 首先创建NSOperation对象, 然后将NSOperation对象放入NSOperationQueue队列中
     */
    
    
    /** 创建NSOperation对象, 因为其是抽象类, 不能直接创建对象, 使用系统的两个子类 */
    
    // 子类1.
    NSInvocationOperation *invocation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(snippet) object:nil];
    
    NSInvocationOperation *invocation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(snippet) object:nil];
    
    
    // 子类2.
    NSBlockOperation *bO1 = [NSBlockOperation blockOperationWithBlock:^{
        [self snippet];
    }];
    
    
    NSBlockOperation *BO2 = [NSBlockOperation blockOperationWithBlock:^{
        [self snippet];
    }];
    
    
    // 创建NSOperationQueue 对象.
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    NSOperationQueue *queue2 = [NSOperationQueue mainQueue];
    
    // 队列最大并发数.
    queue.maxConcurrentOperationCount = 2;
    
    // queue中添加operation对象.
    [queue addOperation:invocation1];
    [queue addOperation:invocation2];
    [queue addOperation:bO1];
    [queue addOperation:BO2];
    
}

#pragma mark - 重点: GCD(Grand Central Dispatch)

#pragma maek - GCD使用场景一:单例
/** GCD的写法(强烈推荐) */
+ (instancetype)defaultViewController {
    
    static ViewController *vc = nil;
    
    // 只执行一次.
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        vc = [[ViewController alloc] init];
    });
    
    return vc;
}


/** 传统的写法 */
+ (instancetype)sharedViewController {
    
    static ViewController *vc = nil;
    
    if (vc == nil) {
        vc = [[ViewController alloc] init];
    }
    
    return vc;
}


#pragma mark - GCD常用场景二: 图片异步加载的实现
- (IBAction)handleGCD:(id)sender {
    
    // 通过GCD开子线程, 执行图片加载(URL方法).
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        NSURL *url = [NSURL URLWithString:@"http://img5.cache.netease.com/3g/2015/10/30/20151030124521c1f7e.jpg"];
        
        NSData *data = [NSData dataWithContentsOfURL:url];
        
        UIImage *image = [UIImage imageWithData:data];
        
        
        // GCD返回主线程, UI赋值.
        dispatch_async(dispatch_get_main_queue()
                       , ^{
                           
                           self.imageView.image = image;
                           
                       });
        
    });
    
}



#pragma mark - 多线程管理(GCD)
- (IBAction)handleGCDManager:(id)sender {
    
    /**
     * GCD核心是队列管理, 和NSOperationQueue很相似, 但GCD是函数实现, 效率高, 推荐使用
     *
     * GCD的队列分两种类型: 串行, 并行.
     *
     * GCD中自带一个串行队列(即主队列- 主线程)
     * GCD中自带4个并行队列(通过get_global...)
     */
    
#if 0 /** 获取GCD的主队列(串行队列) */
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    
    dispatch_async(mainQueue, ^{
        [self snippet];
    });
    
#endif
    
    
#if 0 /** 获取GCD自带的并行队列 */
    
    dispatch_queue_t globelQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    // 向队列中异步分发任务.
    dispatch_async(globelQueue, ^{
        [self snippet];
    });
    
#endif
    
    
#if 0 /** 手动创建串行队列 */
    
    dispatch_queue_t serialQueue = dispatch_queue_create("com.example.myqueue", DISPATCH_QUEUE_SERIAL);
    
    // 异步分发任务.
    dispatch_async(serialQueue, ^{
        [self snippet];
    });
    
    dispatch_async(serialQueue, ^{
        [self snippet];
    });
    
    dispatch_async(serialQueue, ^{
        [self snippet];
    });
#endif
    
#if 1 /** 手动创建并行队列 */
    
    dispatch_queue_t andQuque = dispatch_queue_create("com.baidu.www", DISPATCH_QUEUE_CONCURRENT);
    
    
    dispatch_async(andQuque, ^{
        [self snippet];
    });
    
    dispatch_async(andQuque, ^{
        [self snippet];
    });
    
#endif
    
}



#pragma mark -
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)dealloc {
    [_imageView release];
    [super dealloc];
}
@end
